<template>
    <h2>待办清单</h2>
    <input type="text" v-model="title" @keydown.enter="addTodo" />
    <button v-if="active < all" @click="clear">清理</button>

    <transition-group name="flip-list" tag="ul" v-if="todos.length">
        <li v-for="(todo, i) in todos" :key="todo.title">
            <input type="checkbox" v-model="todo.done" />
            <span :class="{ done: todo.done }">{{ todo.title }}</span>
            <span class="remove-btn" @click="removeTodo($event, i)"> ❌ </span>
        </li>
    </transition-group>
    <div v-else>暂无数据</div>

    <div>
        全选 <input type="checkbox" v-model="allDone" />
        <span>{{ active }} / {{ all }}</span>
    </div>

    <transition name="modal">
        <div class="info-wrapper" v-if="showModal">
            <div class="info">哥，你啥也没有输入！</div>
        </div>
    </transition>

    <span class="dustbin">🗑️</span>
    <div class="animate-wrap">
        <transition
            @before-enter="beforeEnter"
            @enter="enter"
            @after-enter="afterEnter"
        >
            <div class="animate" v-show="animate.show">📃</div>
        </transition>
    </div>
</template>

<script setup lang="ts">
import { ref, computed, reactive } from 'vue';
import { useStorage } from '../utils/storage.js';

let {
    title,
    todos,
    clear,
    addTodo,
    removeTodo,
    active,
    all,
    allDone,
    showModal,
    animate,
    beforeEnter,
    enter,
    afterEnter,
} = useTodos();

function useTodos() {
    let title = ref('');
    let todos = useStorage('todos');
    let animate = reactive({
        show: false,
        el: null,
    });

    let showModal = ref(false);

    function removeTodo(e, i) {
        animate.el = e.target;
        animate.show = true;
        todos.value.splice(i, 1);
    }

    function addTodo() {
        if (!title.value) {
            showModal.value = true;
            setTimeout(() => {
                showModal.value = false;
            }, 1500);
            return;
        }

        todos.value.push({
            title: title.value,
            done: false,
        });

        title.value = '';
    }

    function clear() {
        todos.value = todos.value.filter((v) => !v.done);
    }

    let active = computed(() => todos.value.filter((v) => !v.done).length);
    let all = computed(() => todos.value.length);
    let allDone = computed({
        get: () => active.value === 0,
        set: (value) => todos.value.forEach((todo) => (todo.done = value)),
    });

    function beforeEnter(el) {
        let dom = animate.el;
        let rect = dom.getBoundingClientRect();
        let x = window.innerWidth - rect.left - 60;
        let y = rect.top - 10;
        el.style.transform = `translate(-${x}px, ${y}px)`;
    }

    function enter(el, done) {
        document.body.offsetHeight;
        el.style.transform = `translate(0, 0)`;
        el.addEventListener('transitionend', done);
    }

    function afterEnter(el) {
        animate.show = false;
        el.style.display = 'none';
    }

    return {
        title,
        todos,
        addTodo,
        removeTodo,
        clear,
        active,
        all,
        allDone,
        showModal,
        animate,
        beforeEnter,
        enter,
        afterEnter,
    };
}
</script>

<style>
.done {
    text-decoration: line-through;
    color: gray;
}

.info-wrapper {
    position: fixed;
    top: 20px;
    width: 200px;
}

.info {
    padding: 20px;
    color: white;
    background: #d88986;
}

.modal-enter-from,
.modal-leave-to {
    opacity: 0;
    transform: translateY(-60px);
}

.modal-enter-active,
.modal-leave-active {
    transition: all 0.3s ease;
}

.flip-list-move {
    transition: transform 0.8s ease;
}

.flip-list-enter-active,
.flip-list-leave-active {
    transition: all 0.5s ease;
}

.flip-list-enter-from,
.flip-list-leave-to {
    opacity: 0;
    transform: translateX(30px);
}

.flip-list-leave-active {
    position: absolute;
}

.animate-wrap .animate {
    position: fixed;
    right: 10px;
    top: 10px;
    z-index: 100px;
    transition: all 0.5s linear;
}
</style>
